// Copyright (c) 2020 Presto Labs Pte. Ltd.
// Author: daniel

#pragma once

#include <functional>
#include <memory>
#include <string>
#include <utility>

namespace FIX {
class Message;
}

namespace coin2::exchange::base::order {
struct OrderExecution;
}

namespace coin2::exchange::base::symbology {
class IProduct;
class IProductHolder;
}  // namespace coin2::exchange::base::symbology

namespace coin2::exchange::ftx_common::api_order::fix {

constexpr auto AUTOMATED_EXECUTION_NO_INTERVENTION = '1';
constexpr auto MARKET = '1';
constexpr auto LIMIT = '2';
constexpr auto BUY = '1';
constexpr auto SELL = '2';
constexpr auto GOOD_TILL_CANCEL = '1';
constexpr auto IMMEDIATE_OR_CANCEL = '3';
constexpr auto REDUCE_ONLY = "E";
constexpr auto POST_ONLY = "6";
constexpr auto EMPTY = "";

using IProduct = coin2::exchange::base::symbology::IProduct;
using IProductHolder = coin2::exchange::base::symbology::IProductHolder;
using GetProductHolderFunc =
    std::function<const IProductHolder*(const IProduct& product, int64_t timestamp)>;

/********************************************************************************
 * struct FtxOrder                                                              *
 ********************************************************************************/
struct FtxOrder {
  using OrderExecution = coin2::exchange::base::order::OrderExecution;

  std::string client_id;
  std::string symbol;
  char type;
  double quantity;
  double price;
  char side;
  char time_in_force;
  std::string exec_inst;
  char handlinst;

  explicit FtxOrder(const OrderExecution&, GetProductHolderFunc get_product_holder);
  void Parse(const OrderExecution&, GetProductHolderFunc get_product_holder);
  void Validate() const;
};

/********************************************************************************
 * class FixMessageBuilder                                                      *
 ********************************************************************************/
class FixMessageBuilder {
 public:
  using RequestTypePtr = std::unique_ptr<FIX::Message>;
  using OrderExecution = coin2::exchange::base::order::OrderExecution;

  FixMessageBuilder() = default;
  ~FixMessageBuilder() = default;
  FixMessageBuilder(const FixMessageBuilder&) = delete;
  FixMessageBuilder& operator=(const FixMessageBuilder&) = delete;

  RequestTypePtr GeneratePlaceOrder(
      const OrderExecution& ord_exec,
      GetProductHolderFunc get_product_holder);
  RequestTypePtr GenerateCancelOrder(const OrderExecution& ord_exec);
  RequestTypePtr GenerateQueryOrder(const OrderExecution& ord_exec);
};

}  // namespace coin2::exchange::ftx_common::api_order::fix
